﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;

namespace EmbeddedLanguage.SubProcessors
{
    public class StaticMappingVisitor : ExpressionVisitor
    {
        public Dictionary<string, string> StaticExpressions = new Dictionary<string,string>();
        public Dictionary<string, string> MethodAssociations = new Dictionary<string,string>();

        public Dictionary<string, string> Constructors = new Dictionary<string,string>();

        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            this.Visit(node.Body);
            return node;
        }

        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Arguments.Count == 3)
            {
                if (node.Method.Name.StartsWith("AssignStatic"))
                {
                    var compiledExpr = node.Arguments[1];
                    var compiledMember = compiledExpr as MemberExpression;
                    var expr = node.Arguments[2];
                    var exprMember = expr as MemberExpression;
                    if (
                        (exprMember.Member.Name == exprMember.Member.ReflectedType.Name + "__")
                        &&
                        (compiledMember.Member.Name == exprMember.Member.ReflectedType.Name + "_")
                    )
                    {
                        this.Constructors[exprMember.Member.Name] = compiledMember.Member.Name;
                    }
                    else
                    {
                        this.StaticExpressions[exprMember.Member.Name] = compiledMember.Member.Name;
                    }
                }
                else if (node.Method.Name.StartsWith("Associate_"))
                {
                    var compiledExpr = node.Arguments[1];
                    var compiledMember = compiledExpr as MemberExpression;
                    var method = node.Arguments[2];
                    var methodMember = method as UnaryExpression;
                    var oper = methodMember.Operand;
                    var methodCallExpr = oper as MethodCallExpression;
                    var methodItself = methodCallExpr.Arguments[2] as ConstantExpression;// as System.Linq.Expressions.ConstantExpression;
                    var methodT = methodItself.Value as MethodBase;
                    //string typeS = methodItself.GetType().FullName;
                    this.MethodAssociations[compiledMember.Member.Name] = methodT.Name;
                }
            }
            return base.VisitMethodCall(node);
            //return node;
        }
    }
}
